"""
学术研究自动化Web应用

提供响应式Web界面，包括：
- 用户认证和授权
- 研究项目管理
- 数据分析和可视化
- 协作功能
- 系统管理
"""
import os
import json
from datetime import datetime, timedelta
from functools import wraps
from typing import Dict, Any, Optional

from flask import Flask, render_template, request, jsonify, session, redirect, url_for, flash
from flask_cors import CORS
from werkzeug.security import generate_password_hash, check_password_hash

# 导入我们的服务
from research_automation.services.security_service import SecurityService, UserRole, Permission
from research_automation.services.data_security_service import DataSecurityService, DataClassification
from research_automation.services.input_validation_service import InputValidationService, ValidationLevel


class ResearchAutomationApp:
    """学术研究自动化Web应用"""
    
    def __init__(self):
        self.app = Flask(__name__, 
                        template_folder='templates',
                        static_folder='static')
        
        # 配置
        self.app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
        self.app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=24)
        
        # 启用CORS
        CORS(self.app)
        
        # 初始化服务
        self.security_service = SecurityService(secret_key=self.app.config['SECRET_KEY'])
        self.data_security_service = DataSecurityService()
        self.validation_service = InputValidationService(ValidationLevel.STANDARD)
        
        # 注册路由
        self._register_routes()
        
        # 注册错误处理器
        self._register_error_handlers()
        
        # 注册模板过滤器
        self._register_template_filters()
    
    def _register_routes(self):
        """注册路由"""
        
        # 主页和认证路由
        @self.app.route('/')
        def index():
            """主页"""
            if 'user_id' in session:
                return redirect(url_for('dashboard'))
            return render_template('index.html')
        
        @self.app.route('/login', methods=['GET', 'POST'])
        def login():
            """用户登录"""
            if request.method == 'POST':
                data = request.get_json() if request.is_json else request.form
                username = data.get('username', '').strip()
                password = data.get('password', '')
                
                # 输入验证
                validation_result = self.validation_service.validate_input(
                    username, 
                    context="username",
                    source_ip=request.remote_addr
                )
                
                if not validation_result.result.value == 'valid':
                    return jsonify({
                        'success': False,
                        'error': '用户名格式无效'
                    }), 400
                
                # 用户认证
                auth_result = self.security_service.authenticate_user(
                    username, 
                    password,
                    request.remote_addr
                )
                
                if auth_result['success']:
                    # 设置会话
                    session['user_id'] = auth_result['user']['user_id']
                    session['username'] = auth_result['user']['username']
                    session['role'] = auth_result['user']['role']
                    session['permissions'] = auth_result['user']['permissions']
                    session['token'] = auth_result['token']
                    session.permanent = True
                    
                    if request.is_json:
                        return jsonify({
                            'success': True,
                            'redirect': url_for('dashboard'),
                            'user': auth_result['user']
                        })
                    else:
                        flash('登录成功！', 'success')
                        return redirect(url_for('dashboard'))
                else:
                    if request.is_json:
                        return jsonify({
                            'success': False,
                            'error': auth_result['error']
                        }), 401
                    else:
                        flash(auth_result['error'], 'error')
            
            return render_template('auth/login.html')
        
        @self.app.route('/register', methods=['GET', 'POST'])
        def register():
            """用户注册"""
            if request.method == 'POST':
                data = request.get_json() if request.is_json else request.form
                username = data.get('username', '').strip()
                email = data.get('email', '').strip()
                password = data.get('password', '')
                role = data.get('role', 'student')
                
                # 输入验证
                for field, value in [('username', username), ('email', email)]:
                    validation_result = self.validation_service.validate_input(
                        value,
                        context=field,
                        source_ip=request.remote_addr
                    )
                    
                    if not validation_result.result.value == 'valid':
                        return jsonify({
                            'success': False,
                            'error': f'{field}格式无效'
                        }), 400
                
                # 用户注册
                try:
                    user_role = UserRole(role) if role in [r.value for r in UserRole] else UserRole.STUDENT
                except ValueError:
                    user_role = UserRole.STUDENT
                
                register_result = self.security_service.register_user(
                    username, email, password, user_role
                )
                
                if register_result['success']:
                    if request.is_json:
                        return jsonify({
                            'success': True,
                            'message': '注册成功，请登录',
                            'redirect': url_for('login')
                        })
                    else:
                        flash('注册成功，请登录！', 'success')
                        return redirect(url_for('login'))
                else:
                    if request.is_json:
                        return jsonify({
                            'success': False,
                            'error': register_result['error']
                        }), 400
                    else:
                        flash(register_result['error'], 'error')
            
            return render_template('auth/register.html')
        
        @self.app.route('/logout')
        def logout():
            """用户登出"""
            if 'session_id' in session:
                self.security_service.logout_user(session.get('session_id', ''))
            
            session.clear()
            flash('已成功登出', 'info')
            return redirect(url_for('index'))
        
        # 仪表板和主要功能路由
        @self.app.route('/dashboard')
        @self.require_login
        def dashboard():
            """用户仪表板"""
            user_info = self.get_current_user()
            
            # 获取用户统计信息
            stats = {
                'projects': 5,  # 示例数据
                'analyses': 12,
                'collaborations': 3,
                'recent_activity': [
                    {'action': '创建新项目', 'time': '2小时前'},
                    {'action': '完成数据分析', 'time': '1天前'},
                    {'action': '加入协作项目', 'time': '3天前'}
                ]
            }
            
            return render_template('dashboard/index.html', 
                                 user=user_info, 
                                 stats=stats)
        
        @self.app.route('/projects')
        @self.require_login
        def projects():
            """项目管理"""
            user_info = self.get_current_user()
            
            # 示例项目数据
            projects = [
                {
                    'id': 1,
                    'name': '人工智能在医疗诊断中的应用',
                    'status': '进行中',
                    'progress': 65,
                    'created_at': '2024-01-15',
                    'collaborators': 3
                },
                {
                    'id': 2,
                    'name': '机器学习算法优化研究',
                    'status': '已完成',
                    'progress': 100,
                    'created_at': '2023-11-20',
                    'collaborators': 2
                }
            ]
            
            return render_template('projects/index.html', 
                                 user=user_info, 
                                 projects=projects)
        
        @self.app.route('/projects/create', methods=['GET', 'POST'])
        @self.require_login
        @self.require_permission(Permission.CREATE_RESEARCH)
        def create_project():
            """创建新项目"""
            if request.method == 'POST':
                data = request.get_json() if request.is_json else request.form
                
                project_data = {
                    'name': data.get('name', '').strip(),
                    'description': data.get('description', '').strip(),
                    'category': data.get('category', ''),
                    'privacy_level': data.get('privacy_level', 'internal')
                }
                
                # 输入验证
                for field, value in project_data.items():
                    if isinstance(value, str) and value:
                        validation_result = self.validation_service.validate_input(
                            value,
                            context=f"project_{field}",
                            source_ip=request.remote_addr
                        )
                        
                        if not validation_result.result.value == 'valid':
                            return jsonify({
                                'success': False,
                                'error': f'{field}包含无效内容'
                            }), 400
                
                # 数据加密存储（如果是机密项目）
                if project_data['privacy_level'] == 'confidential':
                    classification = DataClassification.CONFIDENTIAL
                else:
                    classification = DataClassification.INTERNAL
                
                encrypt_result = self.data_security_service.encrypt_data(
                    data=project_data,
                    classification=classification,
                    user_id=session['user_id']
                )
                
                if encrypt_result['success']:
                    # 这里应该保存到数据库
                    project_id = f"proj_{encrypt_result['data_id']}"
                    
                    if request.is_json:
                        return jsonify({
                            'success': True,
                            'project_id': project_id,
                            'message': '项目创建成功'
                        })
                    else:
                        flash('项目创建成功！', 'success')
                        return redirect(url_for('projects'))
                else:
                    return jsonify({
                        'success': False,
                        'error': '项目创建失败'
                    }), 500
            
            return render_template('projects/create.html')
        
        @self.app.route('/analysis')
        @self.require_login
        def analysis():
            """数据分析"""
            user_info = self.get_current_user()
            
            # 示例分析数据
            analyses = [
                {
                    'id': 1,
                    'name': '用户行为分析',
                    'type': '统计分析',
                    'status': '完成',
                    'created_at': '2024-01-20'
                },
                {
                    'id': 2,
                    'name': '实验数据可视化',
                    'type': '数据可视化',
                    'status': '进行中',
                    'created_at': '2024-01-25'
                }
            ]
            
            return render_template('analysis/index.html', 
                                 user=user_info, 
                                 analyses=analyses)
        
        @self.app.route('/collaboration')
        @self.require_login
        def collaboration():
            """协作管理"""
            user_info = self.get_current_user()
            
            # 示例协作数据
            collaborations = [
                {
                    'id': 1,
                    'project': '跨学科研究项目',
                    'role': '主要研究员',
                    'members': 5,
                    'status': '活跃'
                },
                {
                    'id': 2,
                    'project': '数据共享计划',
                    'role': '参与者',
                    'members': 8,
                    'status': '待审核'
                }
            ]
            
            return render_template('collaboration/index.html', 
                                 user=user_info, 
                                 collaborations=collaborations)
        
        @self.app.route('/settings')
        @self.require_login
        def settings():
            """用户设置"""
            user_info = self.get_current_user()
            return render_template('settings/index.html', user=user_info)
        
        @self.app.route('/admin')
        @self.require_login
        @self.require_permission(Permission.MANAGE_SYSTEM)
        def admin():
            """系统管理"""
            user_info = self.get_current_user()
            
            # 获取系统统计
            security_stats = self.security_service.get_security_stats()
            validation_stats = self.validation_service.get_validation_statistics()
            
            return render_template('admin/index.html', 
                                 user=user_info,
                                 security_stats=security_stats,
                                 validation_stats=validation_stats)
        
        # API路由
        @self.app.route('/api/user/profile')
        @self.require_login
        def api_user_profile():
            """获取用户资料API"""
            user_info = self.security_service.get_user_info(session['user_id'])
            if user_info:
                # 移除敏感信息
                safe_info = {
                    'user_id': user_info['user_id'],
                    'username': user_info['username'],
                    'email': user_info['email'],
                    'role': user_info['role'],
                    'created_at': user_info['created_at'],
                    'last_login': user_info['last_login']
                }
                return jsonify({'success': True, 'user': safe_info})
            else:
                return jsonify({'success': False, 'error': '用户不存在'}), 404
        
        @self.app.route('/api/security/events')
        @self.require_login
        @self.require_permission(Permission.VIEW_LOGS)
        def api_security_events():
            """获取安全事件API"""
            limit = min(int(request.args.get('limit', 50)), 100)
            events = self.security_service.get_security_events(limit=limit)
            return jsonify({'success': True, 'events': events})
        
        @self.app.route('/api/validation/stats')
        @self.require_login
        @self.require_permission(Permission.VIEW_LOGS)
        def api_validation_stats():
            """获取验证统计API"""
            stats = self.validation_service.get_validation_statistics()
            return jsonify({'success': True, 'stats': stats})
    
    def _register_error_handlers(self):
        """注册错误处理器"""
        
        @self.app.errorhandler(404)
        def not_found(error):
            if request.is_json:
                return jsonify({'error': '页面不存在'}), 404
            return render_template('errors/404.html'), 404
        
        @self.app.errorhandler(403)
        def forbidden(error):
            if request.is_json:
                return jsonify({'error': '权限不足'}), 403
            return render_template('errors/403.html'), 403
        
        @self.app.errorhandler(500)
        def internal_error(error):
            if request.is_json:
                return jsonify({'error': '服务器内部错误'}), 500
            return render_template('errors/500.html'), 500
    
    def _register_template_filters(self):
        """注册模板过滤器"""
        
        @self.app.template_filter('datetime')
        def datetime_filter(value):
            """日期时间格式化"""
            if isinstance(value, str):
                try:
                    value = datetime.fromisoformat(value.replace('Z', '+00:00'))
                except:
                    return value
            
            if isinstance(value, datetime):
                return value.strftime('%Y-%m-%d %H:%M:%S')
            return value
        
        @self.app.template_filter('timeago')
        def timeago_filter(value):
            """相对时间格式化"""
            if isinstance(value, str):
                try:
                    value = datetime.fromisoformat(value.replace('Z', '+00:00'))
                except:
                    return value
            
            if isinstance(value, datetime):
                now = datetime.now()
                diff = now - value
                
                if diff.days > 0:
                    return f"{diff.days}天前"
                elif diff.seconds > 3600:
                    return f"{diff.seconds // 3600}小时前"
                elif diff.seconds > 60:
                    return f"{diff.seconds // 60}分钟前"
                else:
                    return "刚刚"
            return value
    
    def require_login(self, f):
        """登录装饰器"""
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if 'user_id' not in session:
                if request.is_json:
                    return jsonify({'error': '需要登录'}), 401
                return redirect(url_for('login'))
            
            # 验证令牌
            if 'token' in session:
                token_result = self.security_service.verify_token(session['token'])
                if not token_result['valid']:
                    session.clear()
                    if request.is_json:
                        return jsonify({'error': '会话已过期'}), 401
                    flash('会话已过期，请重新登录', 'warning')
                    return redirect(url_for('login'))
            
            return f(*args, **kwargs)
        return decorated_function
    
    def require_permission(self, permission: Permission):
        """权限检查装饰器"""
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                if not self.security_service.check_permission(session['user_id'], permission):
                    if request.is_json:
                        return jsonify({'error': '权限不足'}), 403
                    flash('权限不足', 'error')
                    return redirect(url_for('dashboard'))
                return f(*args, **kwargs)
            return decorated_function
        return decorator
    
    def get_current_user(self) -> Optional[Dict[str, Any]]:
        """获取当前用户信息"""
        if 'user_id' in session:
            return {
                'user_id': session['user_id'],
                'username': session['username'],
                'role': session['role'],
                'permissions': session.get('permissions', [])
            }
        return None
    
    def run(self, host='127.0.0.1', port=5000, debug=False):
        """运行应用"""
        self.app.run(host=host, port=port, debug=debug)


# 创建应用实例
def create_app():
    """创建Flask应用"""
    return ResearchAutomationApp()


if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)